﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Data.SqlClient;
using System.Data;
using System.DirectoryServices;
using iTextSharp.text;
using iTextSharp.text.pdf;

//////////////////////////////////////////////////////////////////////////
//SharedFunctions.cs                                                    //
//Last Edited: 23 Mar 2012                                              //
//                                                                      //
//This file contains helper functions used throughout the application.  //
//////////////////////////////////////////////////////////////////////////
public class SharedFunctions
{

    public enum UserLevel { NONE, ADVISEE, ADVISOR, ADMIN };

    public SharedFunctions()
    {
    }

    public static String getAdviseeID(HttpRequest request)
    {
        return getIDNumber(request, true);
    }

    public static String getAdvisorID(HttpRequest request)
    {
        return getIDNumber(request, false);
    }
    public static void displayPopupViolations(List<String> violations)
    {
        if (violations.Count == 0)
            return;
        foreach (String s in violations)
        {
            MessageBox.Show(s);
        }
    }

    /// <summary>
    /// generateKey()
    /// 
    /// Creates an arbitrary key from the adviseeID provided
    /// 
    /// Authored by: Eric Bergquist
    /// </summary>
    /// <param name="adviseeID">The adviseeID to generate the key for</param>
    public static String generateKey(String adviseeID)
    {
        int temp = Convert.ToInt32(adviseeID);
        temp += 15263;
        temp = temp >> 2;
        return temp.ToString();
    }//end generateKey()

    //Compresses courses and elective into one object
    public static List<String> checkOneCoursePreCoReqViolations(String courseID, String term, List<Course> courses, List<Elective> electives)
    {

        Dictionary<String, Object> result = StoredProcedures.getCourse(courseID);
        Course course = new Course("" + result["courseID"], result["dpt"].ToString(), result["num"].ToString(), result["name"].ToString(),
            Convert.ToDouble(result["credits"]), term);
        List<Course> coursesAndElectives = new List<Course>();
        foreach (Course c in courses)
        {
            coursesAndElectives.Add(c);
        }
        foreach (Elective e in electives)
        {
            coursesAndElectives.Add(e);
        }
        return checkOneCoursePreCoReqViolations(course, coursesAndElectives);
    }
    public static List<String> checkOneCoursePreCoReqViolations(Course course, List<Course> courses, List<Elective> electives)
    {
        List<Course> coursesAndElectives = new List<Course>();
        foreach (Course c in courses)
        {
            coursesAndElectives.Add(c);
        }
        foreach (Elective e in electives)
        {
            coursesAndElectives.Add(e);
        }
        return checkOneCoursePreCoReqViolations(course, coursesAndElectives);
    }
    //This is where the courses are checked for violations
    public static List<String> checkOneCoursePreCoReqViolations(Course course, List<Course> coursesAndElectives)
    {
        List<String> violations = new List<String>();
        String courseID = "-1";
        int termCode = Convert.ToInt32(course.getTerm());
        if (course is Elective)
        {
            courseID = ((Elective)course).getSelectedCourseID();
        }
        else
            courseID = course.getCourseID();
        List<Dictionary<String, Object>> preReqs = StoredProcedures.getCoursePrereqs(courseID.ToString());
        List<Dictionary<String, Object>> coReqs = StoredProcedures.getCourseCoreqs(courseID.ToString());
        if (preReqs.Count != 0)
        {
            foreach (Dictionary<String, Object> i in preReqs)
            {
                Boolean violation = true;
                foreach (Course c2 in coursesAndElectives)
                {
                    String preReqID = "-1";
                    if (c2 is Elective)
                    {
                        preReqID = ((Elective)c2).getSelectedCourseID();
                    }
                    else
                        preReqID = c2.getCourseID();
                    if (i["courseID"].Equals(preReqID))
                    {
                        if (Convert.ToInt32(c2.getTerm()) >= termCode)
                            violations.Add("Prereq violation: " + c2.getName() + " does not occur before " + course.getName());
                        violation = false;
                        break;
                    }
                }
                if (violation)
                {
                    violations.Add("Prereq violation for " + course.getName() + ": " + i["name"] + " does not exist in the schedule");
                }
            }
        }
        if (coReqs.Count != 0)
        {
            foreach (Dictionary<String, Object> i in coReqs)
            {
                Boolean violation = true;
                foreach (Course c2 in coursesAndElectives)
                {
                    String coReqID = "-1";
                    if (c2 is Elective)
                    {
                        coReqID = ((Elective)c2).getSelectedCourseID();
                    }
                    else
                        coReqID = c2.getCourseID();
                    if (i["courseID"].Equals(coReqID))
                    {
                        if ((Convert.ToInt32(c2.getTerm()) > termCode))
                            violations.Add("Coreq violation: " + c2.getName() + " occurs after " + course.getName());
                        violation = false;
                        break;
                    }
                }
                if (violation)
                {
                    violations.Add("Coreq violation for " + course.getName() + ": " + i["name"] + " does not exist in the schedule");
                }
            }
        }
        return violations;
    }//end checkOneCoursePreCoReqViolations()


    /// <summary>
    /// 
    /// checkStudentSchedule
    /// 
    /// Merges courses and electives into a single list.
    /// Crosschecks list of courses with transcript
    /// checks if there are any pre or co req violations
    /// 
    /// Authored By: Kekai Ariola
    /// Modified By: Eric Bergquist
    /// 
    /// </summary>
    /// <param name="IDnumber"> AdviseeID number, if null will only check courses and electives for pre/coreq violations</param>
    /// <param name="courses"> Courses in schedule</param>
    /// <param name="electives"> Electives in schedule</param>
    /// <returns> <Dictionary<Sting,Object>> This contains a [K,V] pair for every course that has some violation, where
    /// the Key is the string of the courseID and the Value is the dictionary containing keys "course", "violation", and
    /// iff the violation is  pre/coreq, "message". The return Dictionary also contains 1 [K,V] pair with key "violationMessage"
    /// and V is a List<String> that contains all of the messages from the pre/coreq violations</returns>
    public static Dictionary<String, Object> checkSchedule(String adviseeID, List<Course> courses, List<Elective> electives)
    {
        
        List<Course> coursesAndElectives = new List<Course>();
        foreach (Course c in courses)
        {
            coursesAndElectives.Add(c);
        }
        foreach (Elective e in electives)
        {
            coursesAndElectives.Add(e);
        }

        //In violations there will be [K, V] pairs of [courseID, Dictionary<String, Object> violations] for each course
        //and a single pair [messages, List<String>] that contains all of the error messages to be printed.
        Dictionary<String, Object> violations = new Dictionary<String, Object>();
        List<String> violationMessages = new List<String>();    

        //Get List of transcript violations with keys of the dictionaries being "course", "violation" and "message" 
        List<Dictionary<String, Object>> preCoReqViolations = checkPreCoReqViolations(adviseeID, coursesAndElectives);

        foreach (Dictionary<String, Object> i in preCoReqViolations)
        {
            if(!violations.ContainsKey("" + i["course"]))
            {
                violations.Add("" + i["course"], i);
            }
            violationMessages.Add(i["message"].ToString());
        }

        if (adviseeID == null)
        {
            violations.Add("violationMessages", violationMessages);
            return violations;
        }

        //check for transcipt violations, if that course did not have a pre/coreq violation add it to the dictionary
        //otherwise update the dictinary with the transcript violation if it is a higher priority...BORDERLINE or FAIL
        List<Dictionary<String, Object>> transcriptViolations = crossCheckTranscript(adviseeID, coursesAndElectives);
        foreach (Dictionary<String, Object> j in transcriptViolations)
        {
            if (!violations.ContainsKey("" + j["course"]))
            {
                violations.Add("" + j["course"], j);
            }
            else
            {
                if (j["violation"].Equals("BORDERLINE") || j["violation"].Equals("FAIL"))
                {
                    ((Dictionary<String, Object>)violations[""+j["course"]])["violation"] = j["violation"]; 
                }
            }
        }
        violations.Add("violationMessages", violationMessages);

        return violations;
    }//end checkStudentSchedule

    
    /// <summary>
    /// 
    /// Takes merged list of all courses and elective in schedule and checks for pre
    /// and co-req violations
    /// 
    /// Authored by: Kekai Ariola
    /// </summary>
    /// <param name="coursesAndElectives"> merged list of courses and electives </param>
    /// <returns> List<Dictionary<String,Object>> courses in violation</returns>
    public static List<Dictionary<String, Object>> checkPreCoReqViolations(String adviseeID, List<Course> coursesAndElectives)
    {
        //List of Violating Courses
        List<Dictionary<String, Object>> preCoReqColoring = new List<Dictionary<String, Object>>();
        
        //if the advisee is not null get their start term and don't check courses before that(transfer credits)
        //otherwise we're checking a template and check everything
        int startTerm;
        if (adviseeID != null)
        {
            startTerm = Convert.ToInt32(convertToTermCode(getAdviseeStartYear(adviseeID), getAdviseeStartSemester(adviseeID)));
        }
        else
        {
            startTerm = 0;
        }
        //Loop through courses and electives in schedule
        foreach (Course c1 in coursesAndElectives)
        {
            //Do not check courses in transfer credit columns
            if (Convert.ToInt32(c1.getTerm()) >= startTerm)
            {
                //course variables
                String courseID = "-1";
                if (c1 is Elective)
                    courseID = ((Elective)c1).getSelectedCourseID();
                else
                    courseID = c1.getCourseID();
                String courseName = c1.getName();
                int termCode = Convert.ToInt32(c1.getTerm());
                List<Dictionary<String, Object>> preReqs = StoredProcedures.getCoursePrerequisites(courseID.ToString());
                List<Dictionary<String, Object>> coReqs = StoredProcedures.getCourseCoreqs(courseID.ToString());

                //set up dictionary if course is a violation
                Dictionary<String, Object> badCourse = new Dictionary<String, Object>();
                badCourse.Add("course", "");
                badCourse.Add("violation", "");
                badCourse.Add("message", "");

                Boolean inBoth = false;

                if (preReqs.Count != 0 && coReqs.Count != 0)
                {
                    foreach (Dictionary<String, Object> i in preReqs)
                    {
                        foreach (Dictionary<String, Object> j in coReqs)
                        {
                            String coReqID = "" + j["dpt"] + j["num"];
                            if(j["dpt"].ToString().Equals(i["dpt"].ToString()))
                            {
                                if(i["preReqHigh"] != System.DBNull.Value) 
                                {
                                    for(int k = Convert.ToInt32(""+i["preReqLow"]); k < Convert.ToInt32(""+i["preReqHigh"]); k++)
                                    {
                                        if(k == Convert.ToInt32(""+j["num"]))
                                        {
                                            inBoth = true;
                                        }
                                    }
                                }
                                else 
                                {
                                    if(i["preReqLow"].ToString().Equals(j["num"].ToString()))
                                    {
                                        inBoth = true;
                                    }
                                }
                            }
                        }
                    }
                }
                //Check for Prereq violations
                if (preReqs.Count != 0)
                {
                    String lastSet = preReqs.ElementAt(0)["preReqSet"].ToString();
                    String lastSubset = preReqs.ElementAt(0)["preReqSubset"].ToString();

                    //violations.Add("Prereq Violation(s) for " + courseID + " " + courseName + ":");
                    //badCourse.Add("message", "Prereq Violation(s) for " + courseID + " " + courseName + ":");
                    badCourse["message"] = "Prereq Violation(s) for " + courseID + " " + courseName + ":$";

                    String addViolation = ") does not exist in schedule";
                    String addViolationHolder = "";
                    String wrongOrder = " does not occur before " + courseID;
                    Boolean OrReqMet = false;
                    Boolean allSameSet = true;
                    //Loop through PreReqs
                    foreach (Dictionary<String, Object> i in preReqs)
                    {
                        String preReqCourseID = "" + i["dpt"] + i["preReqLow"];
                        String preReqCourseName = "";

                        int preReqCourseIDlow = Convert.ToInt32("" + i["preReqLow"]);
                        int preReqCourseIDhigh = -1;

                        //CHECK IF THIS IS A RANGE
                        if (i["preReqHigh"] != System.DBNull.Value)
                        {
                            preReqCourseIDhigh = Convert.ToInt32("" + i["preReqHigh"]);
                            //WE WON'T BE USING preReqCourseName;
                        }
                        else
                        {
                            //Checks if courseID exists in courseTable
                            if (StoredProcedures.getCourse(preReqCourseID) != null)
                                preReqCourseName = "" + StoredProcedures.getCourse(preReqCourseID)["name"];
                            else
                                continue;
                        }

                        String currentSet = "" + i["preReqSet"];
                        String currentSubset = "" + i["preReqSubset"];
                        Boolean found = false;
                        String currentCourseID = "NOT USED";
                        String currentCourseName = "NOT USED";

                        //SAME SET, SAME SUBSET, AND RELATION
                        if (currentSet.Equals(lastSet) && currentSubset.Equals(lastSubset))
                        {
                            //-------------------------LOOP THROUGH SCHEDULE---------------------------------
                            foreach (Course c2 in coursesAndElectives) //all courses in student schedule
                            {
                                //set currentCourseID
                                if (c2 is Elective)
                                {
                                    currentCourseID = ((Elective)c2).getSelectedCourseID();
                                }
                                else
                                {
                                    currentCourseID = c2.getCourseID();
                                }
                                currentCourseName = c2.getName();

                                //PREREQ IS NOT A RANGE OF COURSES
                                if (preReqCourseIDhigh == -1)
                                {
                                    //PREREQ FOUND...
                                    if (preReqCourseID.Equals(currentCourseID))
                                    {
                                        //AND SATISFIES COREQ AS WELL
                                        if (inBoth && Convert.ToInt32(c2.getTerm()) <= termCode)
                                        {
                                            Dictionary<String, Object> toRemove = coReqs.Find(item => item["dpt"] == i["dpt"] && item["num"] == i["preReqLow"]);
                                            coReqs.Remove(toRemove);
                                        }
                                        //BUT NOT IN RIGHT SPOT
                                        else if (Convert.ToInt32(c2.getTerm()) >= termCode)
                                        {
                                            wrongOrder = currentCourseID + " " + currentCourseName + wrongOrder;
                                        }
                                        found = true;
                                        OrReqMet = true;
                                        break;
                                    }
                                }
                                //PREREQ ACCEPTS A RANGE OF COURSES
                                else
                                {
                                    for (int x = preReqCourseIDlow; x <= preReqCourseIDhigh; x++)
                                    {
                                        String tempCourseID = "" + i["dpt"] + x;
                                        //PREREQ FOUND...
                                        if (tempCourseID.Equals(currentCourseID))
                                        {
                                            //AND SATISFIES COREQ AS WELL
                                            if (inBoth && Convert.ToInt32(c2.getTerm()) <= termCode)
                                            {
                                                Dictionary<String, Object> toRemove = coReqs.Find(item => item["dpt"] == i["dpt"] && item["num"] == i["preReqLow"]);
                                                coReqs.Remove(toRemove);
                                            }
                                            //BUT NOT IN RIGHT SPOT
                                            if (Convert.ToInt32(c2.getTerm()) >= termCode)
                                            {
                                                wrongOrder = currentCourseID + " " + currentCourseName + wrongOrder;
                                            }
                                            found = true;
                                            OrReqMet = true;
                                            //again!!! WHY DO I BREAK!!
                                            break;
                                        }
                                    }//end for
                                    if (found)
                                        break;
                                }//end else
                            }
                            //----------------------------END LOOP-----------------------------------------------
                            //PREREQ NOT IN SCHEDULE 
                            if (!found && preReqCourseIDhigh == -1)
                            {
                                // 28 is the length of addViolation if it hasn't been modified
                                if (addViolation.Length > 28)
                                    addViolationHolder = preReqCourseID + " " + preReqCourseName + " AND " + addViolation;
                                else if (addViolationHolder.Length > 0)
                                    addViolationHolder = preReqCourseID + " " + preReqCourseName + " AND " + addViolationHolder;
                                else
                                    addViolationHolder = preReqCourseID + " " + preReqCourseName + addViolation;
                            }
                            else if (!found && preReqCourseIDhigh != -1)
                            {
                                if (addViolation.Length > 28)
                                    addViolationHolder = preReqCourseID + " - " + preReqCourseIDhigh + " AND " + addViolation;
                                else if (addViolationHolder.Length > 0)
                                    addViolationHolder = preReqCourseID + " - " + preReqCourseIDhigh + " AND " + addViolationHolder;
                                else
                                    addViolationHolder = preReqCourseID + " - " + preReqCourseIDhigh + addViolation;
                            }


                            lastSet = currentSet;
                            lastSubset = currentSubset;
                        }
                        //SAME SET, DIFFERENT SUBSET, OR RELATION (IF ONE IS ALREADY FOUND HOWEVER, NO NEED TO DISPLAY THE OTHER!
                        if (currentSet.Equals(lastSet) && !currentSubset.Equals(lastSubset))
                        {
                            //-------------------------LOOP THROUGH SCHEDULE---------------------------------
                            foreach (Course c2 in coursesAndElectives) //all courses in student schedule
                            {
                                //set currentCourseID
                                if (c2 is Elective)
                                {
                                    currentCourseID = ((Elective)c2).getSelectedCourseID();
                                }
                                else
                                    currentCourseID = c2.getCourseID();
                                currentCourseName = c2.getName();

                                if (preReqCourseIDhigh == -1)
                                {
                                    //PREREQ FOUND...
                                    if (preReqCourseID.Equals(currentCourseID))
                                    {
                                        //AND SATISFIES COREQ AS WELL
                                        if (inBoth && Convert.ToInt32(c2.getTerm()) <= termCode)
                                        {
                                            Dictionary<String, Object> toRemove = coReqs.Find(item => item["dpt"] == i["dpt"] && item["num"] == i["preReqLow"]);
                                            coReqs.Remove(toRemove);
                                        }
                                        //BUT NOT IN RIGHT SPOT
                                        if (Convert.ToInt32(c2.getTerm()) >= termCode)
                                        {
                                            wrongOrder = currentCourseID + " " + currentCourseName + wrongOrder;
                                        }
                                        found = true;
                                        OrReqMet = true;
                                        break;
                                    }
                                }
                                else
                                {
                                    for (int x = preReqCourseIDlow; x <= preReqCourseIDhigh; x++)
                                    {
                                        String tempCourseID = "" + i["dpt"] + x;
                                        //PREREQ FOUND...
                                        if (tempCourseID.Equals(currentCourseID))
                                        {
                                            //AND SATISFIES COREQ AS WELL
                                            if (inBoth && Convert.ToInt32(c2.getTerm()) <= termCode)
                                            {
                                                Dictionary<String, Object> toRemove = coReqs.Find(item => item["dpt"] == i["dpt"] && item["num"] == i["preReqLow"]);
                                                coReqs.Remove(toRemove);
                                            }
                                            //BUT NOT IN RIGHT SPOT
                                            if (Convert.ToInt32(c2.getTerm()) >= termCode)
                                            {
                                                wrongOrder = currentCourseID + " " + currentCourseName + wrongOrder;
                                            }
                                            found = true;
                                            OrReqMet = true;
                                            break;
                                        }
                                    }//end for
                                    if (found)
                                        break;
                                }//end else
                            }
                            //----------------------------END LOOP-----------------------------------------------
                            //PREREQ NOT IN SCHEDULE 
                            if (!found && preReqCourseIDhigh == -1)
                            {
                                // 28 is the length of addViolation if it hasn't been modified
                                if (addViolation.Length > 28)
                                    addViolation = preReqCourseID + " " + preReqCourseName + " OR " + addViolation;
                                else if (addViolationHolder.Length > 0)
                                    addViolation = preReqCourseID + " " + preReqCourseName + " OR " + addViolationHolder;
                                //else
                                //    addViolation = preReqCourseID + " " + preReqCourseName + addViolation;
                            }
                            else if (!found && preReqCourseIDhigh != -1)
                            {
                                // 28 is the length of addViolation if it hasn't been modified
                                if (addViolation.Length > 28)
                                    addViolation = preReqCourseID + " - " + preReqCourseIDhigh + " OR " + addViolation;
                                else if (addViolationHolder.Length > 0)
                                    addViolation = preReqCourseID + " - " + preReqCourseIDhigh + " OR " + addViolationHolder;
                            }
                            allSameSet = false;
                            lastSet = currentSet;
                            lastSubset = currentSubset;
                        }
                        //DIFFERENT SET, AND RELATION
                        if (!currentSet.Equals(lastSet))
                        {
                            //-------------------------LOOP THROUGH SCHEDULE---------------------------------
                            foreach (Course c2 in coursesAndElectives) //all courses in student schedule
                            {
                                //set currentCourseID
                                if (c2 is Elective)
                                {
                                    currentCourseID = ((Elective)c2).getSelectedCourseID();
                                }
                                else
                                    currentCourseID = c2.getCourseID();
                                currentCourseName = c2.getName();

                                if (preReqCourseIDhigh == -1)
                                {
                                    //PREREQ FOUND...
                                    if (preReqCourseID.Equals(currentCourseID))
                                    {
                                        //AND SATISFIES COREQ AS WELL
                                        if (inBoth && Convert.ToInt32(c2.getTerm()) <= termCode)
                                        {
                                            Dictionary<String, Object> toRemove = coReqs.Find(item => item["dpt"] == i["dpt"] && item["num"] == i["preReqLow"]);
                                            coReqs.Remove(toRemove);
                                        }
                                        //BUT NOT IN RIGHT SPOT
                                        if (Convert.ToInt32(c2.getTerm()) >= termCode)
                                        {
                                            wrongOrder = currentCourseID + " " + currentCourseName + wrongOrder;
                                        }
                                        found = true;
                                        OrReqMet = true;
                                        break;
                                    }
                                }
                                else
                                {
                                    for (int x = preReqCourseIDlow; x <= preReqCourseIDhigh; x++)
                                    {
                                        String tempCourseID = "" + i["dpt"] + x;
                                        //PREREQ FOUND...
                                        if (tempCourseID.Equals(currentCourseID))
                                        {
                                            //AND SATISFIES COREQ AS WELL
                                            if (inBoth && Convert.ToInt32(c2.getTerm()) <= termCode)
                                            {
                                                Dictionary<String, Object> toRemove = coReqs.Find(item => item["dpt"] == i["dpt"] && item["num"] == i["preReqLow"]);
                                                coReqs.Remove(toRemove);
                                            }
                                            //BUT NOT IN RIGHT SPOT
                                            if (Convert.ToInt32(c2.getTerm()) >= termCode)
                                            {
                                                wrongOrder = currentCourseID + " " + currentCourseName + wrongOrder;
                                            }
                                            found = true;
                                            OrReqMet = true;
                                            break;
                                        }
                                    }//end for
                                    if (found)
                                        break;
                                }//end else
                            }
                            //----------------------------END LOOP-----------------------------------------------
                            //PREREQ NOT IN SCHEDULE 
                            if (!found && preReqCourseIDhigh == -1)
                            {
                                // 28 is the length of addViolation if it hasn't been modified
                                if (addViolation.Length > 28)
                                    addViolation = preReqCourseID + " " + preReqCourseName + ") AND (" + addViolation;
                                else
                                    addViolation = preReqCourseID + " " + preReqCourseName + addViolation;
                            }
                            else if (!found && preReqCourseIDhigh != -1)
                            {
                                // 28 is the length of addViolation if it hasn't been modified
                                if (addViolation.Length > 28)
                                    addViolation = preReqCourseID + " - " + preReqCourseIDhigh + ") AND (" + addViolation;
                                else
                                    addViolation = preReqCourseID + " - " + preReqCourseIDhigh + addViolation;
                            }

                            allSameSet = false;
                            lastSet = currentSet;
                            lastSubset = currentSubset;
                        } // End Loop through Prereqs
                    }
                    //ADD strings to message
                    if (wrongOrder.Length > 30)
                    {
                        badCourse["course"] = courseID;
                        badCourse["violation"] = "preReq";
                        badCourse["message"] += "\t--" + wrongOrder + " " + courseName + "$";

                    }
                    if (addViolation.Length > 28)
                    {
                        badCourse["course"] = courseID;
                        badCourse["violation"] = "preReq";
                        badCourse["message"] += "\t--(" + addViolation + "$";

                    }
                    if (addViolationHolder.Length > 0 && !(addViolation.Length > 28) && (!OrReqMet || allSameSet))
                    {
                        badCourse["course"] = courseID;
                        badCourse["violation"] = "preReq";
                        badCourse["message"] += "\t--(" + addViolationHolder + "$";

                    }

                    //If list only contains header, remove header
                    if (badCourse["message"].ToString().Equals("Prereq Violation(s) for " + courseID + " " + courseName + ":$"))
                    {
                        badCourse["message"] = "";
                    }
                } //end preReq checking
                //co-req checking
                if (coReqs.Count != 0)
                {
                    foreach (Dictionary<String, Object> i in coReqs)
                    {
                        String coReqCourseID = "" + i["courseID"];
                        String coReqCourseName = "" + i["name"];
                        Boolean violation = true;
                        String currentCourseID = "NOT USED";
                        //loop through schedule
                        foreach (Course c2 in coursesAndElectives)
                        {
                            if (c2 is Elective)
                            {
                                currentCourseID = ((Elective)c2).getSelectedCourseID();
                            }
                            else
                                currentCourseID = c2.getCourseID();
                            //FOUND CO-REQ...
                            if (coReqCourseID.Equals(currentCourseID))
                            {
                                //BUT NOT IN RIGHT TERM
                                if ((Convert.ToInt32(c2.getTerm()) > termCode))
                                {
                                    badCourse["message"] += "Coreq Violation(s) for " + courseID + " " + courseName + ":$";
                                    badCourse["message"] += "   -" + currentCourseID + " " + c2.getName() + " occurs after " + courseID + " " + courseName + "$";
                                }
                                violation = false;
                                break;
                            }
                        }
                        //CO-REQ NOT FOUND
                        if (violation)
                        {
                            if (!badCourse["violation"].Equals("preReq"))
                            {
                                badCourse["message"] += "Coreq Violation(s) for " + courseID + " " + courseName + ":" + "$";
                                badCourse["violation"] = "coReq";
                            }
                            badCourse["message"] += "   -" + coReqCourseID + " " + coReqCourseName + " does not exist in the schedule" + "$";
                            badCourse["course"] = courseID;
                        }
                    }
                }
                if (!badCourse["course"].Equals(""))
                    preCoReqColoring.Add(badCourse);
            }
        }
        return preCoReqColoring;
    }// End checkPreCoReqViolations()

    
    /// <summary>
    /// crossCheckTranscript
    /// 
    /// Checks courses in schedule versus courses in transcript
    /// 
    /// POSSIBLE "GRADE" Values:
    ///  PASS (NO COLORING)
    ///  BORDERLINE (COLORED)
    ///  FAIL (COLORED)
    ///  NULL (NULL GRADE, RIGHT SPOT) (COLORED)
    ///  MISSING (NO RECORD OF COURSE) (COLORED)
    ///  WRONG(COURSE RECORD IN DIFFERENT TERM, PREVIOUS OR ) (COLORED)
    /// 
    /// Authored By: Kekai Ariola
    /// </summary>
    /// <param name="adviseeID"> Advisee ID </param>
    /// <param name="coursesAndElectives"> Merged list of courses and electives </param>
    /// <returns>coursesToColor</returns>
    public static List<Dictionary<String, Object>> crossCheckTranscript(String adviseeID, List<Course> coursesAndElectives)
    {
        //Transcript from Banner
        List<Dictionary<String, Object>> transcript = StoredProcedures.getAdviseeTranscript(adviseeID);
        //List of courses to color
        List<Dictionary<String, Object>> coursesToColor = new List<Dictionary<String, Object>>();

        String year = DateTime.Now.Year.ToString();
        int month = DateTime.Now.Month;

        String semester = "";
        //Fall from AUGUST TO DECEMBER
        if (month >= 8 && month <= 12)
            semester = "Fall";

        //Spring from JANUARY TO MAY
        else if (month >= 1 && month <= 5)
            semester = "Spring";

        //Summer
        else
            semester = "Summer";

        int currentTerm = Convert.ToInt32(convertToTermCode(year, semester));
        int startTerm = Convert.ToInt32(StoredProcedures.getAdviseeStartTerm(adviseeID)["startTerm"]);
       
        foreach (Course c1 in coursesAndElectives)
        {
            //only check courses between start date and currentTerm
            if (Convert.ToInt32(c1.getTerm()) >= startTerm && Convert.ToInt32(c1.getTerm()) < currentTerm)
            {
                //course variables
                String courseInSchedID = "-1";
                if (c1 is Elective)
                    courseInSchedID = ((Elective)c1).getSelectedCourseID();
                else
                    courseInSchedID = c1.getCourseID();

                String courseName = c1.getName();
                int scheduledTerm = Convert.ToInt32(c1.getTerm());
                Boolean foundCourse = false;

                //Course object
                Dictionary<String, Object> courseAndGrade = new Dictionary<String, Object>();
                courseAndGrade.Add("course", courseInSchedID);
                courseAndGrade.Add("violation", "");
                String grade = "";

                // Loop through Objects in Transcript
                foreach (Dictionary<String, Object> i in transcript)
                {
                    String courseInTransID = "" + i["courseID"];
                    int transcriptTerm = Convert.ToInt32("" + i["term"]);
                    grade = "";

                    //COURSE NOT IN CORRECT TERM
                    if (courseInSchedID.Equals(courseInTransID) && scheduledTerm != transcriptTerm)
                    {
                        //If course was taken more than once, only mark it for the term it is in.
                        if (courseAndGrade["violation"].Equals(""))
                        {
                            grade = "WRONG";
                            courseAndGrade["violation"] = grade;
                            coursesToColor.Add(courseAndGrade);
                        }
                        foundCourse = true;
                    }
                    //COURSE IN SCHEDULE AND IN RIGHT TERM
                    else if (courseInSchedID.Equals(courseInTransID) && scheduledTerm == transcriptTerm)
                    {
                        if (!i["grade"].Equals(System.DBNull.Value))
                            grade = "" + i["grade"];
                        else
                            grade = "NULL";

                        if (!grade.Equals("PASS"))
                        {
                            courseAndGrade["violation"] = grade;
                            coursesToColor.Add(courseAndGrade);
                        }
                        foundCourse = true;
                    }
                }
                //COURSE NOT FOUND
                if (!foundCourse)
                {
                    courseAndGrade["violation"] = "MISSING";
                    coursesToColor.Add(courseAndGrade);
                }
            }
        }
        return coursesToColor;
    }

    /// <summary>
    /// 
    /// displayViolations
    /// 
    /// Modified by: Eric Bergquist
    /// </summary>
    /// <param name="label">Label to output text to</param>
    /// <param name="violations">list of violations to write</param>
    public static void displayViolations(System.Web.UI.WebControls.Label label, List<String> violations)
    {
        //TRY TO BOLD FONT IN HERE!!!
        label.Text = "";
        label.Text += "<strong> Prerequisite and Corequisite information may be out of date. <br /> Check the University Bulletin for the most recent info </strong> <br /> <br />";

        foreach (String s in violations)
        {
            String[] seperateMessages = s.Split('$');
            foreach (String sepM in seperateMessages)
            {
                label.Text = label.Text + "" + sepM + "<br />";
            }
            
        }
    }
    /// <summary>
    /// getIDNumber()
    /// 
    /// Get the user's ID number from Active Directory, given the cookie that exists in the browser.
    /// </summary>
    /// <param name="request">HTTPRequest request - the Request element of the current page</param>
    /// <param name="isAdvisee">bool isAdvisee - true if the user is an advisee, false if the user is an advisor</param>
    /// <returns>The ID number as a string</returns>
    private static String getIDNumber(HttpRequest request, bool isAdvisee)
    {
        //Decrypt the login cookie to obtain user name
        String encryptedTicket = request.Cookies.Get(FormsAuthentication.FormsCookieName).Value;
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(encryptedTicket);
        //Query the Active Directory Server to obtain ID number
        DirectoryEntry entry = new DirectoryEntry("LDAP://campus.up.edu/" + GetDistinguishedName(authTicket.Name).Substring(7));
        String IDnumber = "";
        if (isAdvisee) IDnumber = entry.Properties["description"].Value.ToString();
        else IDnumber = entry.Properties["employeeID"].Value.ToString();

        //Clean up and return
        entry.Close();
        return IDnumber;
    } //end getIDNumber()

    /// <summary>
    /// getAdviseeStartDate()
    /// 
    /// Gets the start year of the advisee - NOTE: Only works with years of length 4.
    /// </summary>
    /// <param name="adviseeID">The ID of the advisee</param>
    /// <returns>The start date in the form: Semester Year. If the advisee does not have a start date, returns "Uninitialized".</returns>
    public static String getAdviseeStartDate(String adviseeID)
    {
        Dictionary<String, Object> result = StoredProcedures.getAdviseeStartTerm(adviseeID);
        String startDate = "Uninitialized";
        if (result != null) startDate = convertFromTermCode(result["startTerm"].ToString());
        return startDate;
    } //end getAdviseeStartDate()

    /// <summary>
    /// getAdviseeStartYear()
    /// 
    /// Gets the starting year of the advisee - NOTE: Only works with years of length 4.
    /// </summary>
    /// <param name="adviseeID">The ID of the advisee</param>
    /// <returns>The year (ex: 2008) the advisee starts. If the advisee does not have a start year, returns a blank string</returns>
    public static String getAdviseeStartYear(String adviseeID)
    {
        String startYear = getAdviseeStartDate(adviseeID);
        if (startYear.Equals("Uninitialized")) startYear = "";
        else startYear = startYear.Substring(startYear.IndexOf(' ') + 1);
        return startYear;
    } // end getAdviseeStartYear()


    /// <summary>
    /// getAdviseeStartSemester()
    /// 
    /// Gets the starting semester of the advisee - NOTE: Only works with years of length 4.
    /// </summary>
    /// <param name="adviseeID">The ID of the advisee</param>
    /// <returns>The semester (ex: Fall) the advisee starts. If the advisee does not have a start semester, returns a blank string</returns>
    public static String getAdviseeStartSemester(String adviseeID)
    {
        String startSemester = getAdviseeStartDate(adviseeID);
        if (startSemester.Equals("Uninitialized")) startSemester = "";
        else startSemester = startSemester.Substring(0, startSemester.IndexOf(' '));
        return startSemester;
    } // end getAdviseeStartSemester()
    /// <summary>
    /// convertToTermCode()
    /// 
    /// Converts a semester and year (ex: Fall 2008) to a term code (ex: 200901)
    /// Will error out if appropriate parameters are not passed.
    /// </summary>
    /// <param name="year">The year to convert (ex: 2008)</param>
    /// <param name="semester">The semester to convert (ex: Fall)</param>
    /// <returns>The term code representation of the semester and year (ex: 200901)</returns>
    public static String convertToTermCode(String year, String semester)
    {
        if (semester.Equals("Fall"))
        {
            semester = "01";
            //Increment the year by one
            int intYear = Convert.ToInt32(year);
            intYear++;
            year = "" + intYear;
            while (year.Length < 4) //handles template years - adding 0's to the front
            {
                year = "0" + year;
            }
        }
        else if (semester.Equals("Spring"))
        {
            semester = "02";
        }
        else if (semester.Equals("Summer"))
        {
            semester = "03";
        }
        return year + semester;
    } // end convertToTermCode()

    /// <summary>
    /// convertFromTermCode()
    /// 
    /// Converts a term code (Ex: 200901) to a semester and year (ex: Fall 2008)
    /// Will fail if an appropriate term code is passed
    /// </summary>
    /// <param name="termCode">The term code to convert from (Ex: 200901)</param>
    /// <returns>A string of the semester and year (ex: Fall 2008) - Returns "Uninitialized" if the term code is an empty string</returns>
    public static String convertFromTermCode(String termCode)
    {
        if (termCode == "")
        {
            return "Uninitialized";
        }
        String year = termCode.Substring(0, 4);
        String semester = termCode.Substring(4, 2);
        if (semester.Equals("01"))
        {
            semester = "Fall";
            //Decrement the year by 1
            int intYear = Convert.ToInt32(year);
            intYear--;
            year = "" + intYear;
        }
        else if (semester.Equals("02"))
        {
            semester = "Spring";
        }
        else if (semester.Equals("03"))
        {
            semester = "Summer";
        }
        return semester + " " + year;
    } // end convertFromTermCode()
    /// <summary>
    /// getDptAcronymToString()
    /// 
    /// Returns a Dictionary of department acronyms and their full names
    /// ex: ("AS", "Aerospace Studies")
    /// </summary>
    /// <returns>Dictionary of department acronyms and their full names</returns>
    public static Dictionary<String, String> getDptAcronymToString()
    {
        Dictionary<String, String> dptAcronymToString = new Dictionary<String, String>();
        dptAcronymToString.Add("AS", "Aerospace Studies");
        dptAcronymToString.Add("BIO", "Biology");
        dptAcronymToString.Add("BUS", "Business Administration");
        dptAcronymToString.Add("CE", "Civil Engineering");
        dptAcronymToString.Add("CHM", "Chemistry");
        dptAcronymToString.Add("CHN", "Chinese");
        dptAcronymToString.Add("CS", "Computer Science");
        dptAcronymToString.Add("CST", "Communication Studies");
        dptAcronymToString.Add("DNC", "Dance");
        dptAcronymToString.Add("DRM", "Drama");
        dptAcronymToString.Add("ECN", "Economics");
        dptAcronymToString.Add("ED", "Education");
        dptAcronymToString.Add("EE", "Electrical Engineering");
        dptAcronymToString.Add("EGR", "Engineering");
        dptAcronymToString.Add("ENG", "English");
        dptAcronymToString.Add("ENV", "Environmental Studies");
        dptAcronymToString.Add("FA", "Fine Arts");
        dptAcronymToString.Add("FL", "Foreign Languages");
        dptAcronymToString.Add("FRN", "French");
        dptAcronymToString.Add("GEO", "Geography");
        dptAcronymToString.Add("GRM", "German");
        dptAcronymToString.Add("HPE", "Health and Physical Education");
        dptAcronymToString.Add("HST", "History");
        dptAcronymToString.Add("ME", "Mechanical Engineering");
        dptAcronymToString.Add("MSL", "Military Science & Leadership");
        dptAcronymToString.Add("MTH", "Mathematics");
        dptAcronymToString.Add("MUS", "Music");
        dptAcronymToString.Add("NRS", "Nursing");
        dptAcronymToString.Add("PCS", "Program in Catholic Studies");
        dptAcronymToString.Add("PHL", "Philosophy");
        dptAcronymToString.Add("PHY", "Physics");
        dptAcronymToString.Add("POL", "Political Science");
        dptAcronymToString.Add("PSY", "Psychology");
        dptAcronymToString.Add("RELI", "Religious Studies");
        dptAcronymToString.Add("SCI", "Science");
        dptAcronymToString.Add("SJP", "Social Justice Program");
        dptAcronymToString.Add("SW", "Social Work");
        dptAcronymToString.Add("SOC", "Sociology");
        dptAcronymToString.Add("SPN", "Spanish");
        dptAcronymToString.Add("THEP", "Theological Perspectives");
        dptAcronymToString.Add("THE", "Theology");
        return dptAcronymToString;
    } //end getDptAcronymToString()

    /// <summary>
    /// runStoredProcedure()
    /// 
    /// Runs the specified stored procedures with the appropriate parameters
    /// </summary>
    /// <param name="storedProcedure"> The name of the stored procedure to run</param>
    /// <param name="parametersAndValues"> A dictionary of the parameter name and the value of the parameter to pass to the stored procedure</param>
    /// <returns>A List of Dictionaries that is the result rows of the stored procedure</returns>
    public static List<Dictionary<String, Object>> runStoredProcedure(String storedProcedure, Dictionary<String, Object> parametersAndValues)
    {
        //Open the connection to the database and set up a stored procedure and add the parameters
        SqlConnection myConnection = new SqlConnection("Data Source=up-mssql4;Initial Catalog=AdviseUP;Integrated Security=True");
        myConnection.Open();
        SqlCommand sqlCommand = new SqlCommand(storedProcedure, myConnection);
        sqlCommand.CommandType = CommandType.StoredProcedure;
        foreach (String s in parametersAndValues.Keys)
        {
            sqlCommand.Parameters.Add(new SqlParameter(s, parametersAndValues[s]));
        }
        //Execute the stored procedure and read the results into a list of dictionaries
        SqlDataReader sqlReader = sqlCommand.ExecuteReader();
        List<Dictionary<String, Object>> results = new List<Dictionary<String, Object>>();
        while (sqlReader.Read())
        {
            Dictionary<String, Object> resultRow = new Dictionary<String, Object>();
            for (int i = 0; i < sqlReader.FieldCount; i++)
            {
                resultRow.Add(sqlReader.GetName(i), sqlReader.GetValue(i));
            }
            results.Add(resultRow);
        }
        //Close the connection and return the list of dictionaries
        sqlReader.Close();
        myConnection.Close();
        return results;
    } // end runStoredProcedure()
    /// <summary>
    /// runScalarStoreProcedure()
    /// 
    /// Runs the specified store procedure with the appropriate parameters - returns an int result rather than result rows
    /// </summary>
    /// <param name="storedProcedure"> The name of the stored procedure </param>
    /// <param name="parametersAndValues"> The name of the parameters and the values of the parameters</param>
    /// <returns>Returns a 1 if the stored procedure ran properly, and a 0 otherwise</returns>
    public static int runScalarStoredProcedure(String storedProcedure, Dictionary<String, Object> parametersAndValues)
    {
        //Connect to the database and set up the stored procedure command and add parameters
        SqlConnection myConnection = new SqlConnection("Data Source=up-mssql4;Initial Catalog=AdviseUP;Integrated Security=True");
        myConnection.Open();
        SqlCommand sqlCommand = new SqlCommand(storedProcedure, myConnection);
        sqlCommand.CommandType = CommandType.StoredProcedure;
        foreach (String s in parametersAndValues.Keys)
        {
            sqlCommand.Parameters.Add(new SqlParameter(s, parametersAndValues[s]));
        }
        //Try the command. If it executed properly, result should be equal to 1
        int result = 0;
        try
        {
            result = sqlCommand.ExecuteNonQuery();
        }
        catch
        {
            //Some error occurred
        }
        //Close the connection and return the result
        myConnection.Close();
        return result;
    } // end runScalarStoredProcedure()

    /// <summary>
    /// getLastCourseID()
    /// 
    /// Get the last course ID modified/added to the database
    /// </summary>
    /// <returns>An integer for the courseID</returns>
    public static int getLastCourseID()
    {
        SqlConnection myConnection = new SqlConnection("Data Source=up-mssql4;Initial Catalog=AdviseUP;Integrated Security=True");
        myConnection.Open();
        SqlCommand sqlCommand = new SqlCommand("getLastCourseID", myConnection);
        sqlCommand.CommandType = CommandType.StoredProcedure;
        int result = Convert.ToInt32(sqlCommand.ExecuteScalar());
        myConnection.Close();
        return result;
    } // end getLastCourseID()

    /// <summary>
    /// getLastTemplateID()
    /// 
    /// Get the last templateID modified/added to the database
    /// </summary>
    /// <returns>An integer for the templateID</returns>
    public static int getLastTemplateID()
    {
        SqlConnection myConnection = new SqlConnection("Data Source=up-mssql4;Initial Catalog=AdviseUP;Integrated Security=True");
        myConnection.Open();
        SqlCommand sqlCommand = new SqlCommand("getLastTemplateID", myConnection);
        sqlCommand.CommandType = CommandType.StoredProcedure;
        int result = Convert.ToInt32(sqlCommand.ExecuteScalar());
        myConnection.Close();
        return result;
    } // end getLastTemplateID()
    /// <summary>
    /// getLastElectiveID()
    /// 
    /// Get the last electiveID modified/added to the database
    /// </summary>
    /// <returns>An integer for the electiveID</returns>
    public static int getLastElectiveID()
    {
        SqlConnection myConnection = new SqlConnection("Data Source=up-mssql4;Initial Catalog=AdviseUP;Integrated Security=True");
        myConnection.Open();
        SqlCommand sqlCommand = new SqlCommand("getLastElectiveID", myConnection);
        sqlCommand.CommandType = CommandType.StoredProcedure;
        int result = Convert.ToInt32(sqlCommand.ExecuteScalar());
        myConnection.Close();
        return result;
    } // end getLastElectiveID()

    public static String GetDistinguishedName(string loginName)
    {
        DirectoryEntry directoryEntry = new DirectoryEntry();
        DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry, "(sAMAccountName=" + loginName + ")");
        SearchResult searchResult = directorySearcher.FindOne();
        return searchResult.Path;
    }
    /// <summary>
    /// convertFromDptAcronymToString()
    /// 
    /// Gets the full name of a department from its department acronym
    /// </summary>
    /// <param name="acronym">The department acronym to convert</param>
    /// <returns>The full name of the department</returns>
    public static String convertFromDptAcronymToString(String acronym)
    {
        Dictionary<String, String> d = getDptAcronymToString();
        return d[acronym];
    } // end convertFromDptAcronymToString()

    /// <summary>
    /// isInitialized()
    /// 
    /// Returns true if the advisee's schedule has been initialized
    /// i.e. has at least 1 course or elective in it.
    /// </summary>
    /// <param name="username">String username - the user's login name</param>
    /// <returns>Whether the advisee is initialized</returns>
    public static Boolean isInitialized(String adviseeID)
    {

        Dictionary<String, Object> numCourse = StoredProcedures.initializedCourses(adviseeID);
        Dictionary<String, Object> numElective = StoredProcedures.initializedElectives(adviseeID);
        if (Convert.ToInt32(numCourse["count"]) + Convert.ToInt32(numElective["count"]) == 0)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    /// <summary>
    /// getuserLevel()
    /// 
    /// Get the level of the current user (Advisee, Advisor, etc.).
    /// </summary>
    /// <param name="username">String username - the user's login name</param>
    /// <returns>An enumeration for the user level</returns>
    public static UserLevel getUserLevel(String username)
    {
        if (isAdvisee(username))
        {
            return UserLevel.ADVISEE;
        }
        else if (isAdmin(username))
        {
            return UserLevel.ADMIN;
        }
        else if (isAdvisor(username))
        {
            return UserLevel.ADVISOR;
        }
        else if (StoredProcedures.fetchAdvisee(username + "@up.edu") == StoredProcedures.SUCCESS)
        {
            return UserLevel.ADVISEE;
        }
        else if (StoredProcedures.fetchAdvisor(username + "@up.edu") == StoredProcedures.SUCCESS)
        {
            return UserLevel.ADVISOR;
        }
        else
        {
            return UserLevel.NONE;
        }
    } //end getUserLevel()

    /// <summary>
    /// isAdvisee()
    /// 
    /// Checks if user is an advisee.
    /// </summary>
    /// <param name="username">String username - the user's login name</param>
    /// <returns>True if and only if the user is an advisee, false otherwise</returns>
    private static bool isAdvisee(String username)
    {
        //Determine whether the advisee exists in the Advisee table.
        if (StoredProcedures.getAdviseeByEmail(username + "@up.edu") != null)
        {
            return true;
        }
        else
        {
            return false;
        }
    } //end isAdvisee()

    /// <summary>
    /// isAdvisor()
    /// 
    /// Checks if user is an advisor.
    /// </summary>
    /// <param name="username">String username - the user's login name</param>
    /// <returns>True if the user is an advisor OR an admin, false otherwise</returns>
    private static bool isAdvisor(String username)
    {
        //Determine whether the advisor exists in the Employee table.
        if (StoredProcedures.getAdvisorByEmail(username + "@up.edu") != null)
            return true;
        else
            return false;
    } //end isAdvisor()

    /// <summary>
    /// isAdmin()
    /// 
    /// Checks if user is an administrator.
    /// </summary>
    /// <param name="username">String username - the user's login name</param>
    /// <returns>True if and only if the user is an admin, false otherwise</returns>
    private static bool isAdmin(String username)
    {
        //If the advisor exists in the table, determine whether they are an administrator.
        //If they are not in the table, or they are not an administrator, return false
        Dictionary<String, Object> result = StoredProcedures.getAdvisorByEmail(username + "@up.edu");
        if (result != null)
        {
            if (Convert.ToInt32(result["isAdministrator"]) == 1)
                return true;
            else
                return false;
        }
        else
            return false;
    } //end isAdmin()

    /// <summary>
    /// 
    /// generatePDF
    /// 
    /// modified by: Kekai Ariola
    /// 
    /// </summary>
    /// <param name="uid">Takes in either the student ID or the template ID</param>
    /// <param name="path">The name of the file that is to be outputted</param>
    /// <param name="courses">List of all courses in schedule</param>
    /// <param name="electives">List of all electives in schedule</param>
    /// <param name="isTemplate">As the name implies...</param>

    public static void generatePDF(String uid, String path, List<Course> courses, List<Elective> electives, bool isTemplate)
    {
        Document doc1 = new Document(PageSize.LETTER, 36f, 36f, 18f, 18f);
        Font arial = FontFactory.GetFont("Arial", 12f, BaseColor.BLACK);
        Font arialBold = FontFactory.GetFont("Arial", 12f, Font.BOLD, BaseColor.BLACK);
        Font bigArial = FontFactory.GetFont("Arial", 14f, Font.BOLD, BaseColor.BLACK);
        Font smallArial = FontFactory.GetFont("Arial", 11f, BaseColor.BLACK);

        List<Course> electivesAndCourses = new List<Course>();
        foreach (Course i in courses)
        {
            electivesAndCourses.Add(i);
        }
        foreach (Elective i in electives)
        {
            electivesAndCourses.Add(i);
        }
        int startYear = 0;
        String startSemester = getAdviseeStartSemester(uid);
        int transferYear = 0;

        PdfWriter.GetInstance(doc1, new FileStream(path, FileMode.Create));
        doc1.Open();
        
        PdfPTable disclaimerTable = new PdfPTable(21);
        disclaimerTable.WidthPercentage = 100f;
        
        PdfPTable t = new PdfPTable(21);
        t.WidthPercentage = 100f;
        
        PdfPCell disTitleCell = new PdfPCell();
        disTitleCell.BorderWidthRight = Rectangle.NO_BORDER;
        disTitleCell.Colspan = 4;
        disTitleCell.HorizontalAlignment = PdfPCell.ALIGN_LEFT;
        PdfPCell disclaimer = new PdfPCell();
        disclaimer.BorderWidthLeft = Rectangle.NO_BORDER;
        disclaimer.Colspan = 17;
        disclaimer.HorizontalAlignment = PdfPCell.ALIGN_LEFT;


        PdfPCell fullCell = new PdfPCell();
        fullCell.Border = Rectangle.NO_BORDER;
        fullCell.Colspan = 21;
        fullCell.HorizontalAlignment = PdfPCell.ALIGN_CENTER;
        PdfPCell titleCell = new PdfPCell();
        titleCell.Border = Rectangle.NO_BORDER;
        titleCell.Colspan = 7;
        titleCell.HorizontalAlignment = PdfPCell.ALIGN_LEFT;
        PdfPCell spacingCell = new PdfPCell();
        spacingCell.Border = Rectangle.NO_BORDER;
        spacingCell.Colspan = 1;
        spacingCell.HorizontalAlignment = PdfPCell.ALIGN_CENTER;
        PdfPCell creditsCell = new PdfPCell();
        creditsCell.Border = Rectangle.NO_BORDER;
        creditsCell.Colspan = 3;
        creditsCell.HorizontalAlignment = PdfPCell.ALIGN_RIGHT;

        disTitleCell.Phrase = new Phrase("DISCLAIMER: ", bigArial);
        disclaimerTable.AddCell(disTitleCell);
        disclaimer.Phrase = new Phrase("THIS DOCUMENT IS FOR PLANNING PURPOSES ONLY. IT IS NOT A TRANSCRIPT.", smallArial);
        disclaimerTable.AddCell(disclaimer);

        fullCell.Phrase = new Phrase(" ");
        t.AddCell(fullCell);
        fullCell.Phrase = new Phrase("University of Portland", arialBold);
        t.AddCell(fullCell);

        if (isTemplate)
        {
            transferYear = 0001;
            String templateName = StoredProcedures.getTemplateName(uid)["name"] as String;
            fullCell.Phrase = new Phrase(templateName);
        }
        else
        {

            if (startSemester.Equals("Fall"))
            {
                startYear = Convert.ToInt32(SharedFunctions.getAdviseeStartYear(uid)) + 1;
                transferYear = startYear - 1;
            }
            else
            {
                startYear = Convert.ToInt32(SharedFunctions.getAdviseeStartYear(uid));
                transferYear = startYear;
            }

            Dictionary<String, object> name = StoredProcedures.getAdviseeName(uid);
            fullCell.Phrase = new Phrase("Name: " + name["firstName"] + " " + name["lastName"], arial);
        }
        t.AddCell(fullCell);

        fullCell.Phrase = new Phrase(" ");
        t.AddCell(fullCell);

        int currYear = transferYear;
        //COUNT STARTS AT 0, for Transfer Credits
        int count = 0;
        while (electivesAndCourses.Count > 0)
        {
            int holder = 0;
            switch (count)
            {
                case 0:
                    fullCell.Phrase = new Phrase("TRANSFER CREDITS", arialBold);
                    holder = 1;
                    break;
                case 1:
                    fullCell.Phrase = new Phrase("FRESHMAN YEAR", arialBold);
                    break;
                case 2:
                    fullCell.Phrase = new Phrase("SOPHOMORE YEAR", arialBold);
                    break;
                case 3:
                    fullCell.Phrase = new Phrase("JUNIOR YEAR", arialBold);
                    break;
                case 4:
                    fullCell.Phrase = new Phrase("SENIOR YEAR", arialBold);
                    break;
                default:
                    fullCell.Phrase = new Phrase("YEAR " + count, arialBold);
                    break;
            }

            List<Course> transfer = new List<Course>();
            double transferCredits = 0;
            List<Course> fall = new List<Course>();
            double fallCredits = 0;
            List<Course> spring = new List<Course>();
            double springCredits = 0;
            List<Course> summer = new List<Course>();
            double summerCredits = 0;
            foreach (Course c in electivesAndCourses)
            {
                int y = Convert.ToInt32(c.getTerm().Substring(0, 4));
                if (!isTemplate)
                { 
                    if (Convert.ToInt32(c.getTerm()) < Convert.ToInt32(convertToTermCode(getAdviseeStartYear(uid), startSemester)))
                    {
                        transfer.Add(c);
                    }
                }
                if (y == currYear)
                {
                    String sem = c.getSemester();
                    if (sem.Equals("Fall"))
                    {
                        fall.Add(c);
                    }
                    else if (sem.Equals("Spring"))
                    {
                        spring.Add(c);
                    }
                    else
                    {
                        summer.Add(c);
                    }
                }
            }
            if (holder == 1 && transfer.Count == 0)
            {
                fullCell.Phrase = new Phrase();
            }
            else
                t.AddCell(fullCell);

            foreach (Course c in transfer)
            {
                electivesAndCourses.Remove(c);
                transferCredits += c.getCredits();
            }
            foreach (Course c in fall)
            {
                electivesAndCourses.Remove(c);
                fallCredits += c.getCredits();
            }
            foreach (Course c in spring)
            {
                electivesAndCourses.Remove(c);
                springCredits += c.getCredits();
            }
            foreach (Course c in summer)
            {
                electivesAndCourses.Remove(c);
                summerCredits += c.getCredits();
            }

            if (holder == 0)
            {
                titleCell.Phrase = new Phrase("Fall Semester", arialBold);
                t.AddCell(titleCell);

                creditsCell.Phrase = new Phrase("Credits: " + fallCredits, arialBold);
                t.AddCell(creditsCell);

                spacingCell.Phrase = new Phrase(" ", arial);
                t.AddCell(spacingCell);

                titleCell.Phrase = new Phrase("Spring Semester", arialBold);
                t.AddCell(titleCell);

                creditsCell.Phrase = new Phrase("Credits: " + springCredits, arialBold);
                t.AddCell(creditsCell);

                while ((fall.Count > 0) || (spring.Count > 0))
                {
                    Course f = null;
                    Course s = null;
                    if (fall.Count > 0) f = fall[0];
                    if (spring.Count > 0) s = spring[0];

                    String fname = " ";
                    if (f != null)
                    {
                        fname = f.getDpt() + f.getNum() + " ";
                        if (f.getName().Length > 20) fname += f.getName().Substring(0, 17) + "...";
                        else fname += f.getName();
                    }
                    titleCell.Phrase = new Phrase(fname, arial);
                    t.AddCell(titleCell);

                    creditsCell.Phrase = new Phrase((f == null) ? " " : ("" + f.getCredits()), arial);
                    t.AddCell(creditsCell);

                    spacingCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(spacingCell);

                    String sname = " ";
                    if (s != null)
                    {
                        sname = s.getDpt() + s.getNum() + " ";
                        if (s.getName().Length > 20) sname += s.getName().Substring(0, 17) + "...";
                        else sname += s.getName();
                    }
                    titleCell.Phrase = new Phrase(sname, arial);
                    t.AddCell(titleCell);

                    creditsCell.Phrase = new Phrase((s == null) ? " " : ("" + s.getCredits()), arial);
                    t.AddCell(creditsCell);

                    if (f != null) fall.Remove(f);
                    if (s != null) spring.Remove(s);
                }
                if (summer.Count > 0)
                {
                    titleCell.Phrase = new Phrase("Summer Semester", arialBold);
                    t.AddCell(titleCell);

                    creditsCell.Phrase = new Phrase("Credits: " + summerCredits, arialBold);
                    t.AddCell(creditsCell);

                    spacingCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(spacingCell);

                    titleCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(titleCell);

                    creditsCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(creditsCell);
                }
                while (summer.Count > 0)
                {
                    Course c = summer[0];

                    String cname = " ";
                    cname = c.getDpt() + c.getNum() + " ";
                    if (c.getName().Length > 20) cname += c.getName().Substring(0, 17) + "...";
                    else cname += c.getName();
                    titleCell.Phrase = new Phrase(cname, arial);
                    t.AddCell(titleCell);

                    creditsCell.Phrase = new Phrase("" + c.getCredits(), arial);
                    t.AddCell(creditsCell);

                    spacingCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(spacingCell);

                    titleCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(titleCell);

                    creditsCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(creditsCell);

                    summer.Remove(c);
                }
            }
            else if (holder == 1 && transferCredits > 0)
            {
                titleCell.Phrase = new Phrase("Transfer Courses", arialBold);
                t.AddCell(titleCell);

                creditsCell.Phrase = new Phrase("Credits: " + transferCredits, arialBold);
                t.AddCell(creditsCell);

                spacingCell.Phrase = new Phrase(" ", arial);
                t.AddCell(spacingCell);

                titleCell.Phrase = new Phrase(" ", arial);
                t.AddCell(titleCell);

                creditsCell.Phrase = new Phrase(" ", arial);
                t.AddCell(creditsCell);
                while (transfer.Count > 0)
                {
                    Course c = transfer[0];

                    String cname = " ";
                    cname = c.getDpt() + c.getNum() + " ";
                    if (c.getName().Length > 20) cname += c.getName().Substring(0, 17) + "...";
                    else cname += c.getName();
                    titleCell.Phrase = new Phrase(cname, arial);
                    t.AddCell(titleCell);

                    creditsCell.Phrase = new Phrase("" + c.getCredits(), arial);
                    t.AddCell(creditsCell);

                    spacingCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(spacingCell);

                    titleCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(titleCell);

                    creditsCell.Phrase = new Phrase(" ", arial);
                    t.AddCell(creditsCell);

                    transfer.Remove(c);
                }
            }
            //else
            //{
            //    fullCell.Phrase = new Phrase(" ");
            //}
            fullCell.Phrase = new Phrase(" ");
            t.AddCell(fullCell);

            currYear += 1;
            count += 1;
        }

        fullCell.Phrase = new Phrase(" ");
        t.AddCell(fullCell);

        fullCell.HorizontalAlignment = PdfPCell.ALIGN_RIGHT;
        fullCell.Phrase = new Phrase("Date Generated: " + DateTime.Now.ToShortDateString(), arial);
        t.AddCell(fullCell);

        doc1.Add(disclaimerTable);
        doc1.Add(t);
        doc1.Close();
    }


}